#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>

#define FOR(i,a,n) for(int i=a,_n(n);i<_n;++i)
#define REP(i,n) FOR(i,0,n)

const int INF = 1<<29;

using namespace std;

class Graph
{
    struct Edge
    {
        int vs,vt,w;
        Edge *next;
        void Set(int a,int b,int c,Edge* nt)
        {
            vs = a, vt = b, w = c, next = nt;
        }
    };
    vector<Edge> edge;
    vector<Edge*> head;
    int vn,arcn;
public:
    Graph(int n,int m)
    {
        vn = n + 1;
        arcn = 0;
        edge.reserve(m+10);
        head.resize(vn,(Edge*)NULL);
    }
    void AddArc(int vs,int vt,int w)
    {
        edge[arcn].Set(vs,vt,w,head[vs]);
        head[vs] = &edge[arcn++];
    }
    int GetAns(int root)
    {
        int ans = 0;
        while(true)
        {
            vector<int> in(vn,INF);
            vector<int> pre(vn,-1);
            in[root] = 0;
            for(Edge *ep=&edge[0];ep!=&edge[arcn];++ep) if(ep->w<in[ep->vt])
            {
                in[ep->vt] = ep->w;
                pre[ep->vt] = ep->vs;
            }
            REP(i,vn) if(in[i]!=INF)
            {
                ans += in[i];
            }
            vector<int> toGi(vn,-1);
            vector<int> done(vn,-1);
            bool canBreak = true;
            REP(i,vn) toGi[i] = i;
            REP(i,vn) if(pre[i]!=-1&&done[i]==-1)
            {
                for(int p=i;p!=-1;p=pre[p])
                {
                    if(done[p]==i)
                    {
                        canBreak = false;
                        for(int q=pre[p];q!=p;q=pre[q])
                        {
                            toGi[q] = p;
                        }
                        break;
                    }
                    else if(done[p]!=-1) break;
                    done[p] = i;
                }
            }
            if(canBreak) break;
            for(Edge *ep=&edge[0];ep!=&edge[arcn];++ep)
            {
                int vt = ep->vt;
                ep->vs = toGi[ep->vs], ep->vt = toGi[ep->vt];
                if(ep->vs==ep->vt) ep->w = INF;
                else if(in[vt]!=INF) ep->w -= in[vt];
            }
        }
        return ans;
    }
};

struct House
{
    int x,y,z;
    int Dist(House h)
    {
        return abs(x-h.x)+abs(y-h.y)+abs(z-h.z);
    }
};

int ReadInt()
{
    char c;
    while((c=getchar())==' '||c=='\n');
    int ans = 0;
    ans = c-'0';
    while((c=getchar())!=' '&&c!='\n') ans=ans*10+c-'0';
    return ans;
}
House house[1010];
int main()
{
    int n,x,y,z;
    while(cin>>n>>x>>y>>z)
    {
        if(!n&&!x&&!y&&!z) break;
        int ss = 0;
        Graph g(n,n*n);
        FOR(i,1,n+1)
        {

            house[i].x = ReadInt();
            house[i].y = ReadInt();
            house[i].z = ReadInt();
            g.AddArc(ss,i,house[i].z*x);
        }
        FOR(i,1,n+1)
        {
            int k;
            cin>>k;
            while(k--)
            {
                int vt,w;
                vt = ReadInt();
                w = house[i].Dist(house[vt])*y;
                if(house[vt].z>house[i].z) w+=z;
                if(vt!=i) g.AddArc(i,vt,w);
            }
        }
        printf("%d\n",g.GetAns(ss));
    }
    return 0;
}
